package com.hi5.stexviewer.rates;

import static com.hi5.util.Validation.empty;
import static com.hi5.util.Validation.notEmpty;
import static com.hi5.util.Validation.state;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.omg.CosNaming.NamingContextPackage.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hi5.stexviewer.domain.Market;
import com.hi5.stexviewer.domain.Rate;
import com.hi5.stexviewer.domain.Stock;
import com.hi5.stexviewer.message.Message;
import com.hi5.stexviewer.message.MessageType;
import com.hi5.stexviewer.message.impl.ThreadCustomer;
import com.hi5.util.Validation;

public class RateSource extends ThreadCustomer {
    private static final Logger LOGGER = LoggerFactory
            .getLogger(RateSource.class);

    private List<RateFetcher> rateFetchers;
    private List<Stock> stocksToFetch;
    private Map<Market, List<Stock>> stocksToFetchByMarket;
    private Map<Market, List<RateFetcher>> rateFetchersByMarket;
    private Long sleepTime = 2000L;

    @Override
    public void run() {
        try {
            int i = 0;
            while (!this.isInterrupted()) {
                Message<Integer> message = new Message<Integer>(this, MessageType.RATES_ARRIVED, i++);
                getCallCenter().send(message);
                Thread.sleep(sleepTime);
            }
//            while (!this.isInterrupted()) {
//                Map<Stock, List<Rate>> toReport = new HashMap<Stock, List<Rate>>();
//                Date now = new Date();
//                for (Entry<Market, List<Stock>> entry : stocksToFetchByMarket
//                        .entrySet()) {
//                    List<Stock> stocksToFetch = entry.getValue();
//                    Map<Stock, List<Rate>> result = null;
//                    for (RateFetcher rateFetcher : rateFetchersByMarket
//                            .get(entry.getKey())) {
//                        result = rateFetcher.getRates(stocksToFetch, now);
//                        if (result != null) {
//                            break;
//                        }
//                    }
//                    toReport.putAll(result);
//                }
//
//                if (notEmpty(toReport)) {
//                    Message<Map<Stock, List<Rate>>> message = new Message<Map<Stock, List<Rate>>>(
//                            this, MessageType.RATES, toReport);
//                    getCallCenter().send(message);
//                }
//
//                Thread.sleep(sleepTime);
//            }
        } catch (InterruptedException e) {
            // Do nothing
        } finally {
            getCallCenter().unsubscribe(this);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
//        state(notEmpty(stocksToFetch), "ratesToFetch cannot be empty");
//        state(notEmpty(rateFetchers), "rateFtchers cannot be empty");
        super.afterPropertiesSet();

//        stocksToFetchByMarket = new HashMap<Market, List<Stock>>();
//        for (Stock stock : stocksToFetch) {
//            Market market = stock.getMarket();
//            List<Stock> stockList = stocksToFetchByMarket.get(market);
//            if (stockList == null) {
//                stockList = new ArrayList<Stock>();
//                stocksToFetchByMarket.put(market, stockList);
//            }
//            stockList.add(stock);
//        }
//
//        rateFetchersByMarket = new HashMap<Market, List<RateFetcher>>();
//        for (Market market : rateFetchersByMarket.keySet()) {
//            List<RateFetcher> rateFetchersOfMarket = new ArrayList<RateFetcher>();
//            for (RateFetcher rateFetcher : rateFetchers) {
//                if (rateFetcher.supports(market)) {
//                    rateFetchersOfMarket.add(rateFetcher);
//                }
//            }
//            rateFetchersByMarket.put(market, rateFetchersOfMarket);
//
//            if (empty(rateFetchersOfMarket)) {
//                LOGGER.error("There is no rate fetcher set for {}",
//                        market.getName());
//            }
//        }
    }

    public void setStocksToFetch(List<Stock> stocksToFetch) {
        this.stocksToFetch = stocksToFetch;
    }

    public void setRateFetchers(List<RateFetcher> rateFetchers) {
        this.rateFetchers = rateFetchers;
    }

    public void setSleepTime(Long sleepTime) {
        this.sleepTime = sleepTime;
    }
}
